/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c), 2003-2011,  Jin Chen and Alan M. MacEachren, GeoVISTA Center, Penn State University
 * Licensed under Simplified BSD License
 *
 *
 * @author: jin Chen 
 * @date: Dec 14, 2005$
 * @version: 1.0
 */
package edu.psu.geovista.app.gmatrix.component;

import edu.psu.geovista.app.gmatrix.toolkit.MatrixUtils;
import edu.psu.geovista.app.vit.pub.utils.VitUtils;
import epoviz.trex.common.swing.frame.tool.BasicMouseTool;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.*;
import java.util.logging.Logger;

public class BannableMatrixHeader extends DfMatrixHeader {
    private static final Logger logger=Logger.getLogger(BannableMatrixHeader.class.getName());
    protected Set<Integer> bannedIndexs =new HashSet<Integer>();
    protected Color defaultLabelColor=Color.BLACK;
    protected Color bannedLabelColor=Color.DARK_GRAY;

    Map popupActions=null;// actions for show up in popup menu when right click the head. The actions must be passed (POPUP_HOST: this) by putValue(), pass value "this" is to get further info (e.g. clickedIndex)
    int clickedIndex=-1; // index of row or column being clicked, used for popup menu


    /**
     * @param indsize independent size
     * @param orient
     */
    public BannableMatrixHeader(int indsize, int orient) {
        super(indsize, orient);
    }

    protected JLabel getCellrender(int i, Rectangle bd) {
        JLabel cellrender = super.getCellrender(i,bd);
        if(this.isBannable(i)){
            //cellrender.setForeground(bannedLabelColor);
            cellrender.setEnabled(false);

        }
        else{
            cellrender.setEnabled(true);
            //cellrender.setForeground(defaultLabelColor);

        }
        return cellrender;
    }

    public boolean isBannable(int index ){
        if(bannedIndexs.contains(index) ){
            return true;
        }
        else{
            return false;
        }
    }

    public Set<Integer> getBannedIndexs() {
        return bannedIndexs;
    }
    protected void toggleBanning(int curselect) {
        if(isBannable(curselect) ){//not bann it

            bannedIndexs.remove(curselect);
        }
        else{//bann it
            //fireAdd(curselect);
            fireRemove(curselect);
            bannedIndexs.add(curselect);
        }
        repaint();
    }
    public  void ban(int curselect){
        bannedIndexs.add(curselect);
        repaint();
    }
    public  void ban(int[] indexs){
        HashSet banned = VitUtils.convertArrayToSet(indexs);
        bannedIndexs.addAll(banned);
        repaint();
    }
    public  void unban(int[] indexs){
        HashSet banned = VitUtils.convertArrayToSet(indexs);
        bannedIndexs.removeAll(banned);
        repaint();
    }
    public  void unban(int curselect){
        bannedIndexs.remove(curselect);
        repaint();
    }
    public void unbanAll(){
        bannedIndexs.clear();
        repaint();
    }

    protected MouseListener getSelectSupport() {
        return new BannableMatrixHeader.MySelectSupport();
    }

    public Map getPopupActions() {
        return popupActions;
    }

    public void setPopupActions(Map popupActions) {
        this.popupActions = popupActions;
    }

    public int getClickedIndex() {
        return clickedIndex;
    }

    public void setClickedIndex(int clickedIndex) {
        this.clickedIndex = clickedIndex;
    }


    class MySelectSupport extends BasicMouseTool {

        public void mouseClicked(MouseEvent e){

            super.mouseClicked(e);
            if(isUnbanAll(e)){  //todo temp solution
                unbanAll();
                return;

            }

            int curselect = findMouseSelection(cp);
            if(SwingUtilities.isLeftMouseButton(e)){//do select

                if(this.isAddSelection(e) ){
                    if(selection.contains(curselect)){
                        fireRemove(curselect);  //for selected row/col, if click again, --> unselect
                    }
                    else
                        fireAdd(curselect);  //select
                    unban(curselect);
                }
                /*else if (isMinusSelection(e)){
                   fireRemove(curselect);
                }*/
                else{

                    fireSelect(curselect);
                    unban(curselect);
                }
            }
            else if(SwingUtilities.isRightMouseButton(e) ){//right click
                if(e.isControlDown()) {
                toggleBanning(curselect);
                }
                else{
                    if (popupActions!=null){
                        clickedIndex = findMouseSelection(cp);
                          MatrixUtils.showPopup(BannableMatrixHeader.this, popupActions,e.getX(), e.getY() );
                    }
                    else{
                        Map actmap = getTestAction();
                        int x = e.getX();
                        int y = e.getY();
                        clickedIndex = findMouseSelection(cp);// the index of row/column currently being clicked on
                        MatrixUtils.showPopup(BannableMatrixHeader.this, actmap,x, y );


                    }
                }

            }

        }

        private Map getTestAction() {

            Action test=new AbstractAction() {
                public void actionPerformed(ActionEvent e) {
                    System.out.println("got a click on head.");
                }
            };
            test.putValue(Action.NAME,"Click");
            ArrayList actions=new ArrayList();
            actions.add(test);
            Map actmap=new HashMap(1);
            actmap.put("Test",actions);
            return actmap;
        }

        private boolean isUnbanAll(MouseEvent e){ //right click + control+shift
            if (e.isShiftDown() &&e.isControlDown() &&
                    SwingUtilities.isLeftMouseButton(e)){
                return true;
            }
            else{
                return false;
            }

        }


        /**
         * extend the method to define ur policy
         * @param e
         * @return
         */
        public boolean isAddSelection(MouseEvent e){
            if(e.isShiftDown() ){//add another selection
                logger.finer("shift key down down, do addSelect");
                return true;
            }
            return false;
        }

        public boolean isMinusSelection(MouseEvent e){
            if (e.isAltDown() ){//substract selection
                logger.finer("alt key down, do minus selection");
                return true;
            }
            return false;
        }


    }//inner class
}
